#include "MonitorWork.h"
#include "global.h"
#include <QThread>
#include <QPointer>
#include <QNetworkReply>
#include <QElapsedTimer>
#include <QVersionNumber>
#include <QProcess>

MonitorWork::MonitorWork(QObject *parent)
    : QObject{parent}
{
    m_networkManager = new QNetworkAccessManager(this);
    if (thread() != QThread::currentThread()) {
        m_networkManager->moveToThread(thread());
    }
}

/**
 * @brief fnMqttSubscribe
 * @return
 * 订阅打开的设备数据
 */
void MonitorWork::fnMqttSubscribe(){
    if(Global::CarouselDevNumber == Global::CurrDevNumber)
        return;
    QString devClientID = "";
    QJsonArray jsonArray = Global::usrBindDevices;
    for (const QJsonValue &value : jsonArray) {
        if(value.toObject().value("devDeviceNumber").toString() == Global::CurrDevNumber){
            devClientID = value.toObject().value("devClientID").toString();
            break;
        }
    }
    if(devClientID == ""){
        emit infoOccurred({"showErrorMessage", "4", "获取客户ID失败，请重试！"});
        return;
    }

    QStringList param;
    param.push_back(QString("%1/%2").arg(devClientID, Global::CurrDevNumber));
    param.push_back("0");
    param.push_back("MqttSubscribe");
    emit MGlobal::fnGetInstance()->CallInsidePageAction(param);
    param.clear();
}

/**
 * @brief fnMqttUnsubscribed
 * 停止设备订阅
 */
void MonitorWork::fnMqttUnsubscribed(){
    QString devClientID = "";
    QJsonArray jsonArray = Global::usrBindDevices;
    for (const QJsonValue &value : jsonArray) {
        if(value.toObject().value("devDeviceNumber").toString() == Global::CurrDevNumber){
            devClientID = value.toObject().value("devClientID").toString();
            break;
        }
    }
    if(devClientID == "")
        return;
    QString topic = QString("%1/%2").arg(devClientID, Global::CurrDevNumber);
    QStringList param;
    param.push_back(topic);
    param.push_back("MqttUnsubscribed");
    emit MGlobal::fnGetInstance()->CallInsidePageAction(param);
    param.clear();
    // 清空缓存
    Global::devDataCache.insert("RealData", {});
}

/**
 * @brief fnCleanInvalidDevice
 * 清理不存在的设备
 */
void MonitorWork::fnCleanInvalidDevice(QStringList lostNumber){
    QJsonObject postInfo;
    postInfo.insert("usrAction","CleanInvalidDevice");
    postInfo.insert("devNumbers", lostNumber.join(","));
    postInfo.insert("usrID",Global::usrLoggedInfo.value("uid").toString());
    QString errMessage = "",
        reqResult = "";
    this->fnHttpRequest(postInfo, errMessage, reqResult);
    if(reqResult == "OK")
        emit MGlobal::fnGetInstance()->CallInsidePageAction({"InvalidDeviceCleanupCompleted"});
}

/**
 * @brief fnHasOptionPasswd
 * 判断是否需要输入密码
 */
void MonitorWork::fnHasOptionPasswd(){
    QString hasOptionPasswd = "true";
    if(Global::strAuthority == "9")
        hasOptionPasswd = "false";
    else if(Global::hasOptionPasswd == "0"){
        QSettings settings(Global::fiConfig, QSettings::IniFormat);
        settings.setIniCodec("utf-8");
        settings.beginGroup("CarouselDate");
        if(settings.contains(Global::CurrDevNumber)){
            QStringList lstValue = settings.value(Global::CurrDevNumber).toString().split(",");
            if(lstValue.size() > 2 && lstValue.at(2).contains("@")){
                qint64 lastTime = lstValue.at(2).split("@").first().toLongLong();
                if(lastTime > 0){
                    qint64 currentTimestamp = QDateTime::currentSecsSinceEpoch();
                    qint64 daysInSeconds = 7 * 24 * 3600;
                    if (currentTimestamp - lastTime <= daysInSeconds)
                        hasOptionPasswd = "false";
                }
            }
        }
        settings.endGroup();
    }
    QStringList params = {"checkHasOptionPasswd", hasOptionPasswd};
    emit infoOccurred(params);
}

/**
 * @brief fnReturnVersion
 * @return
 * 密码对比并返回版本信息
 */
void MonitorWork::fnReturnVersion(){
    // QElapsedTimer timer;
    // timer.start();

    QJsonObject postInfo;
    postInfo.insert("usrAction", "GetDeviceState");
    postInfo.insert("devNumber", Global::CurrDevNumber);

    QString errMessage = "",
        reqResult = "";
    this->fnHttpRequest(postInfo, errMessage, reqResult);

    if(!errMessage.isEmpty()){
        QString errMsg = QString("获取设备数据错误，请重试！\n%1").arg(errMessage);
        emit infoOccurred({"showErrorMessage", "4", errMsg});
        return;
    }

    QJsonParseError jsonError;
    QJsonDocument reqJsonDocument = QJsonDocument::fromJson(reqResult.toUtf8().data(), &jsonError);
    if(reqJsonDocument.isNull() || (jsonError.error != QJsonParseError::NoError)){
        emit infoOccurred({"showErrorMessage", "4", "获取设备数据失败，请重试！"});
        return;
    }

    //QByteArray >> QJsonObject
    QJsonObject reqJsonObject = reqJsonDocument.object();
    QJsonObject RealData = reqJsonObject.value(Global::CurrDevNumber).toObject();
    if(RealData.isEmpty()){
        emit infoOccurred({"showErrorMessage", "4", "获取数据失败！\n设备离线已超过规定时限。"});
        return;
    }

    float version = RealData.value("VersionName").toString().leftRef(3).toFloat();

    QString currDevNumberPasswd = "";
    if(version >= 3){

    }else if(version < 3 && version >= 2){
        currDevNumberPasswd = RealData.value("usrPasswd").toString();
    }else if(version < 2 && version >= 1.5){
        currDevNumberPasswd = RealData.value("UserPassword").toString();
    }else{
        currDevNumberPasswd = RealData.value("DevicePWD").toString();
    }

    if(Global::strAuthority == "9")
        Global::CurrDevNumberPasswd = currDevNumberPasswd;
    else if(Global::hasOptionPasswd == "0"){
        if(Global::CurrDevNumberPasswd == ""){
            QString lastPasswd = "ThisIsInitialPasswd";
            QSettings settings(Global::fiConfig, QSettings::IniFormat);
            settings.setIniCodec("utf-8");
            settings.beginGroup("CarouselDate");
            if(settings.contains(Global::CurrDevNumber)){
                QStringList lstValue = settings.value(Global::CurrDevNumber).toString().split(",");
                if(lstValue.size() > 2 && lstValue.at(2).contains("@"))
                    lastPasswd = lstValue.at(2).split("@").last();
            }
            settings.endGroup();
            Global::CurrDevNumberPasswd = lastPasswd;
        }
    }

    if(currDevNumberPasswd != Global::CurrDevNumberPasswd){
        this->fnMqttUnsubscribed();
        emit infoOccurred({"showErrorMessage", "4", "无此操作权限。\n操作密码不匹配，请重试！"});
        QSettings settings(Global::fiConfig, QSettings::IniFormat);
        settings.setIniCodec("utf-8");
        settings.beginGroup("CarouselDate");
        if(settings.contains(Global::CurrDevNumber)){
            QStringList lstValue = settings.value(Global::CurrDevNumber).toString().split(",");
            if(lstValue.size() > 2){
                lstValue.replace(2, "");
                settings.setValue(Global::CurrDevNumber, lstValue.join(","));
            }
        }
        settings.endGroup();
        return;
    }
    // qint64 elapsedMs = timer.elapsed();  // 获取耗时（毫秒）
    // qDebug() << "fnReturnVersion执行时间:" << elapsedMs << "ms, version:" << version;
    emit versionReceived(version);
}

/**
 * @brief fnCheckNewVersion
 * 检查新版本
 */
void MonitorWork::fnCheckNewVersion(bool isAuto){
    QString errMessage = "",
        reqResult = "";
    QJsonObject postInfo;
    postInfo.insert("usrAction","GetNewVersion");
    postInfo.insert("appID","LrDeviceMonitorUpdata");
    this->fnHttpRequest(postInfo, errMessage, reqResult);

    QJsonParseError jsonError;
    QJsonDocument reqJsonDocument = QJsonDocument::fromJson(reqResult.toUtf8().data(), &jsonError);

    QJsonObject fiData = reqJsonDocument.object();
    if(fiData.isEmpty()){
        if(!isAuto){
            emit infoOccurred({"showErrorMessage", "3", "没有查询到任何版本信息！"});
        }else emit reqSystemVersion(true);
        return;
    }

    QVersionNumber currentVersion = QVersionNumber::fromString(APP_VERSION);
    QVersionNumber otherVersion = QVersionNumber::fromString(fiData.value("versionName").toString());
    if (otherVersion <= currentVersion){
        if(!isAuto)
            emit infoOccurred({"showErrorMessage", "1", "当前版本已是最新版本，无需升级。"});
    }else{
        emit infoOccurred({"showErrorMessage", "5", "发现新版本可升级\n即将启动升级程序，请稍候！"});
        QTimer::singleShot(1000, this, [=](){
            bool success = QProcess::startDetached("MUpgrade.exe",{QString("--appName=%1").arg(qAppName())});
            if(success){
                qApp->closeAllWindows();
                return;
            }
            emit infoOccurred({"showErrorMessage", "1", "启动升级程序失败，请手动升级。"});
        });
    }
    if(isAuto)
        emit reqSystemVersion(true);
}

void MonitorWork::fnHttpRequest(QJsonObject httpParameter,
                                     QString &errMessage,
                                     QString &reqResult){
    if (!m_networkManager) {
        errMessage = "Network manager not initialized";
        return;
    }
    QNetworkRequest request;
    request.setUrl(QUrl(Global::apiInterface));
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);

    QDateTime local((QDateTime::currentDateTime()));
    httpParameter.insert("TOKEN",QString("%1%2").arg(Global::apiToken, local.toString("yyyyMMdd")));

    QJsonDocument httpDocument(httpParameter);
    QByteArray requestData  = httpDocument.toJson(QJsonDocument::Compact);

    QPointer<QNetworkReply> reply = m_networkManager->post(request, requestData);
    if (!reply) {
        errMessage = "Failed to create network reply";
        return;
    }

    QTimer timeoutTimer;
    timeoutTimer.setSingleShot(true);
    QEventLoop eventLoop;

    QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
    QObject::connect(&timeoutTimer, &QTimer::timeout, this, [&]() {
        if (reply && reply->isRunning()) {
            reply->abort();
        }
        eventLoop.quit();
    });

    timeoutTimer.start(5000);
    eventLoop.exec();

    if (reply.isNull()) {
        errMessage = tr("Network reply was deleted prematurely");
        return;
    }

    if (timeoutTimer.isActive()) {
        timeoutTimer.stop();

        if (reply->error() == QNetworkReply::NoError) {
            reqResult = reply->readAll();
        } else {
            errMessage = reply->errorString();
            qWarning() << "Network request failed:" << errMessage
                       << "URL:" << request.url()
                       << "Status:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        }
    } else {
        errMessage = tr("Request timed out");
        qWarning() << "Request timeout for URL:" << request.url();
    }

    if (!reply.isNull())
        reply->deleteLater();
}
